Skip to content

Tavily web search, Bubble Tea wizard, and bug fixes#4

Merged
initializ-mk merged 14 commits into
mainfrom
develop
Feb 23, 2026
Merged

Tavily web search, Bubble Tea wizard, and bug fixes#4
initializ-mk merged 14 commits into
mainfrom
develop

Conversation

@initializ-mk
Copy link
Copy Markdown
Contributor

Summary

  • Add Tavily as a web search provider (skill + built-in tool) alongside Perplexity with auto-detection and explicit provider selection
  • Refactor init wizard from plain prompts to Bubble Tea TUI with multi-step navigation (back/forward), secret input masking, and live validation
  • Add Telegram typing indicator support
  • Fix wizard bugs: esc quit, back-navigation state resets, env var deduplication, egress domain filtering by selected provider

Test plan

  • Run forge init and verify full wizard flow (provider → tools → skills → egress → review)
  • Select web_search tool, verify Tavily/Perplexity provider choice and key validation
  • Select summarize skill with OpenAI provider, verify no duplicate OPENAI_API_KEY prompt
  • Verify esc quits at any step, backspace navigates back, spacebar toggles selections
  • Verify .env file has no duplicate keys
  • Run go test ./... in forge-core and forge-cli

initializ-mk and others added 14 commits February 22, 2026 16:06
Replace the legacy survey-based interactive prompts with a Bubble Tea
terminal UI wizard for `forge init`. Add --theme flag for TUI color
theme selection. Add GitHub Actions job to auto-update the Homebrew
formula on release.
Remove unused legacy prompt helpers (init_prompt.go), delete empty
branch and unused slugRegexp in name_step, remove unused formatDomains
in egress_step, and run gofmt across all TUI source files.
- Add web_search provider abstraction with Tavily (default) and Perplexity backends
- Auto-detect provider from env vars (TAVILY_API_KEY > PERPLEXITY_API_KEY),
  with explicit override via WEB_SEARCH_PROVIDER
- Add tavily-search as external skill with embedded script and registry entry
- Add `forge skills add` command for vendoring registry skills into projects
- Update init wizard with provider selection phase when web_search is chosen
- Send Telegram "typing" chat action while LLM processes requests
- Add CLAUDE.md with pre-commit gofmt and golangci-lint instructions
- Wire validateTavilyKey into the init wizard tools step
- Fix gofmt formatting in skills.go and tools_step.go
- Rename ValidatePerplexityFunc to ValidateWebSearchKeyFunc for both providers
…alidation

- Egress step now only shows the selected web_search provider domain
  (Tavily or Perplexity) instead of both
- Skills step prompts for required_env, one_of_env, and optional_env
  when skills are selected, blocking if required/one_of is not provided
- Web search tool step validates Tavily/Perplexity API keys with async
  validation (same pattern as provider step)
- DeriveEgressFunc now receives envVars to filter provider-specific domains
- Updated tests to match new provider-specific behavior
Tools line now displays "web_search [tavily]" or "web_search [perplexity]"
to indicate which provider was selected.
The review step reads from WizardContext directly, not the tools step
Summary(). Updated Prepare() to annotate web_search with the provider
from ctx.EnvVars.
Init() was not resetting phase, currentPrompt, envPrompts, or envValues.
When the user navigated back from a later step, the stale skillsEnvPhase
with an exhausted currentPrompt caused an index out of range panic.
Skills step now checks env vars collected by earlier wizard steps
(via Prepare/knownEnvVars) so it won't re-prompt for keys like
OPENAI_API_KEY already provided as the model provider. buildEnvVars()
uses a written map to skip duplicate keys when writing the .env file.
Provider step Apply() now stores the API key in ctx.EnvVars
(e.g. OPENAI_API_KEY) so the skills step's Prepare() can detect
it via knownEnvVars and skip the one_of group entirely.
MultiSelect and SingleSelect Init() methods were no-ops that didn't
reset the done flag. After navigating back, done remained true causing
Update() to short-circuit and treat all keys (including space) as
no-ops while the step immediately re-completed.
Three issues fixed:
- Wizard now handles esc globally as quit (matching kbd hints)
- Removed redundant esc→back mapping from review step that caused
  the review↔egress loop
- EgressDisplay.Init() now resets done flag so back-navigation
  doesn't immediately re-advance
Add Tavily web search integration and Telegram typing indicator
@initializ-mk initializ-mk self-assigned this Feb 23, 2026
@initializ-mk initializ-mk merged commit c2f5600 into main Feb 23, 2026
18 checks passed
naveen-kurra pushed a commit to naveen-kurra/forge that referenced this pull request May 23, 2026
…initializ#4)

Reviewer flagged: a user who configures forge.yaml with
'auth: { required: true, providers: [...] }' and then runs the agent
with --no-auth gets anonymous access silently. The flag and the YAML
block were treated independently. The --no-auth happy-path short-circuit
returned an anonymous middleware before consulting cfg.Auth at all.

This is the second-highest-impact misconfiguration class in the auth
subsystem (open prod endpoint by mistake), and it's worse than the
nil-Chain case (initializ#3) because here the operator deliberately wrote
'required: true' into their config.

Fix (graduated severity):
  auth.required == true  + --no-auth  →  startup error (refuse)
  providers populated    + --no-auth  →  warning (operator intent
                                        unclear; we proceed but make
                                        the override visible)
  empty auth block       + --no-auth  →  unchanged (anonymous, no log)

Error message names what's wrong AND lists the three ways to fix it:
  - remove --no-auth
  - set 'auth.required: false'
  - delete the 'auth:' block

Warning includes provider count so dashboards can alert.

Tests (all -race clean):
  TestResolveAuth_NoAuthWithRequiredFails
    auth.required=true + --no-auth → error; message contains
    "--no-auth conflicts with".
  TestResolveAuth_NoAuthWithProvidersWarns
    providers set, required=false + --no-auth → no error, warning
    emitted containing "--no-auth overrides".
  TestResolveAuth_NoAuthWithEmptyYAMLConfig_NoWarning
    Regression: --no-auth alone (no auth: block) still works without
    spurious warning.
  TestResolveAuth_NoAuthWithRequiredFalseAndProviders_WarnsNotFails
    Explicit Required: false is respected — warn, don't refuse.

New recordLogger test helper captures Warn/Info calls so assertions
can check what the runner emitted; mirrors the no-op nopLogger pattern
already in use.

Backward compat:
  - --no-auth alone (no auth: block): unchanged
  - --no-auth + providers + no required: warns, still anonymous
  - --no-auth + required: true: BREAKING — refuses to start. This is
    intentional; the previous behavior silently exposed a "required
    auth" deployment as anonymous, which the user explicitly tried
    to prevent in their forge.yaml.

Verification:
  go test -race ./forge-core/auth/... ./forge-cli/runtime/ — green
  full sweep — 47/47 packages pass
  golangci-lint v2.10.1 — 0 issues
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant